import random
from typing import Dict, Optional

#银行卡
class Card:
    def __init__(self, card_id: str, password: str, money: float):
        self.card_id   = card_id
        self.password  = password
        self.money     = money
        self.is_locked = False

    #银行卡锁定
    def lock(self):
        self.is_locked = True
    #银行卡解锁
    def unlock(self):
        self.is_locked = False


class User:
    def __init__(self, name: str, id_card: str, phone: str, card: Card):
        self.name = name
        self.id_card = id_card
        self.phone = phone
        self.card = card


class Bank:
    #管理员账号密码
    ADMIN_USER = "admin"
    ADMIN_PWD  = "12345"

    def __init__(self):
        self.users = {}          # card_id -> User
        self.admin_fail = 0      # 管理员连续输错次数，值为0：输入错误直接退出银行管理系统

    # 随机生成卡号
    def _generate_card_id(self) -> str:
        while True:
            cid = "".join([str(random.randint(0, 9)) for _ in range(6)])
            if cid not in self.users:
                return cid
    #通过卡号查找用户
    def _get_user_by_card(self, card_id: str):
        return self.users.get(card_id)

    #开户
    def create_user(self):
        print("\n=== 开户 ===")
        name   = input("姓名: ")
        id_card= input("身份证号: ")
        phone  = input("手机号: ")
        money=float(input("预存金额:"))
        # try:
        #     money = float(input("预存金额: "))
        # except ValueError:
        #     print("金额输入非法")
        #     return
        pwd = input("密码: ")
        cid = self._generate_card_id()
        card = Card(cid, pwd, money)
        user = User(name, id_card, phone, card)
        self.users[cid] = user
        print(f"开户成功！卡号：{cid}")

    #查询余额
    def query_money(self):
        print("\n=== 查询 ===")
        cid = input("卡号: ")
        user = self._get_user_by_card(cid)
        if not user:#未找到用户
            print("卡号不存在")
            return
        if user.card.is_locked:
            print("卡已被锁定")
            return
        # 密码验证3次锁定逻辑略
        pwd = input("密码: ")
        if pwd != user.card.password:
            print("密码错误")
            return
        print(f"余额：{user.card.money}")

    def withdraw(self):
        """取款"""
        print("\n=== 取款 ===")
        cid = input("卡号: ")
        user = self._get_user_by_card(cid)
        if not user:
            print("卡号不存在")
            return
        if user.card.is_locked:
            print("卡已被锁定")
            return
        pwd = input("密码: ")
        if pwd != user.card.password:
            print("密码错误")
            return

        amt=float(input("取款金额："))
        # try:
        #     amt = float(input("取款金额: "))
        # except ValueError:
        #     print("金额非法")
        #     return
        if amt <= 0 or amt > user.card.money:
            print("金额非法或余额不足")
            return
        user.card.money -= amt
        print(f"取款成功，余额：{user.card.money}")

    def deposit(self):
        """存款"""
        print("\n=== 存款 ===")
        cid = input("卡号: ")
        user = self._get_user_by_card(cid)
        if not user:
            print("卡号不存在")
            return
        if user.card.is_locked:
            print("卡已被锁定")
            return
        pwd = input("密码: ")
        if pwd != user.card.password:
            print("密码错误")
            return
        try:
            amt = float(input("存款金额: "))
        except ValueError:
            print("金额非法")
            return
        if amt <= 0:
            print("金额必须大于 0")
            return
        user.card.money += amt
        print(f"存款成功，余额：{user.card.money}")

    def transfer(self):
        """转账"""
        print("\n=== 转账 ===")
        out_cid = input("转出卡号: ")
        in_cid  = input("转入卡号: ")
        user_out = self._get_user_by_card(out_cid)
        user_in  = self._get_user_by_card(in_cid)
        if not user_out or not user_in:
            print("卡号不存在")
            return
        if user_out.card.is_locked or user_in.card.is_locked:
            print("有卡被锁定")
            return
        pwd = input("转出卡密码: ")
        if pwd != user_out.card.password:
            print("密码错误")
            return
        try:
            amt = float(input("转账金额: "))
        except ValueError:
            print("金额非法")
            return
        if amt <= 0 or amt > user_out.card.money:
            print("金额非法或余额不足")
            return
        confirm = input("确认转账？(y/n): ")
        if confirm.lower() == 'y':
            user_out.card.money -= amt
            user_in.card.money  += amt
            print("转账成功")
        else:
            print("取消转账")

    def lock_card(self):
        """锁定"""
        print("\n=== 锁定 ===")
        cid = input("卡号: ")
        user = self._get_user_by_card(cid)
        if not user:
            print("卡号不存在")
            return
        pwd = input("密码: ")
        if pwd != user.card.password:
            print("密码错误")
            return
        user.card.lock()
        print("锁定成功")

    def unlock_card(self):
        """解锁"""
        print("\n=== 解锁 ===")
        cid = input("卡号: ")
        user = self._get_user_by_card(cid)
        if not user:
            print("卡号不存在")
            return
        pwd = input("密码: ")
        if pwd != user.card.password:
            print("密码错误")
            return
        user.card.unlock()
        print("解锁成功")

    # ------------- 主循环 -------------
    def welcome(self):
        print("******************************************")
        print("***                                    ***")
        print("***        欢迎登录银行管理系统         ***")
        print("***                                    ***")
        print("******************************************")

    def menu(self):
        print("******************************************")
        print("***   1.开户(1)            2.查询(2)    ***")
        print("***   3.取款(3)            4.存款(4)    ***")
        print("***   5.转账(5)            6.锁定(6)    ***")
        print("***   7.解锁(7)                        ***")
        print("***                                   ***")
        print("***    退出(Q)                         ***")
        print("******************************************")

    def check_admin(self) -> bool:
        """登录管理员校验"""
        for _ in range(3):
            u = input("请输入管理员账户：")
            p = input("请输入密码：")
            if u == self.ADMIN_USER and p == self.ADMIN_PWD:
                print("操作成功，请稍后...")
                return True
            print("管理员账户或密码输入错误...")
        return False

    def main_loop(self):
        self.welcome()
        if not self.check_admin():
            print("多次错误，系统退出")
            return

        while True:
            self.menu()
            choice = input(">>> ").strip().upper()
            if choice == "1":
                self.create_user()
            elif choice == "2":
                self.query_money()
            elif choice == "3":
                self.withdraw()
            elif choice == "4":
                self.deposit()
            elif choice == "5":
                self.transfer()
            elif choice == "6":
                self.lock_card()
            elif choice == "7":
                self.unlock_card()
            elif choice == "Q":
                # 退出时再验证一次管理员
                if self.check_admin():
                    print("系统已退出")
                    break
                else:
                    print("验证失败，返回菜单")
            else:
                print("输入无效")
